#import "OpenGLMapView.h"

@implementation OpenGLMapView

- (id)init {
	NSLog(@"%@", NSStringFromSelector( _cmd ));
	return self;
}

- (id)initWithFrame:(NSRect)frameRect {
	NSLog(@"%@", NSStringFromSelector( _cmd ));
	return self;
}
- (id)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat*)format
{
	NSLog(@"%@", NSStringFromSelector( _cmd ));
	GLuint attribs[] = 
	{
		NSOpenGLPFANoRecovery,
		NSOpenGLPFAWindow,
		NSOpenGLPFAAccelerated,
		NSOpenGLPFADoubleBuffer,
		NSOpenGLPFAColorSize, 24,
		NSOpenGLPFAAlphaSize, 8,
		NSOpenGLPFADepthSize, 24,
		NSOpenGLPFAStencilSize, 8,
		NSOpenGLPFAAccumSize, 0,
		0
	};

	NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: (NSOpenGLPixelFormatAttribute*) attribs]; 

	if (!fmt) {
		NSLog(@"No OpenGL pixel format");
	}
	
	self = [super initWithFrame:frameRect pixelFormat:fmt];
	if( self ) {
	}
	return self;
}

- (void)awakeFromNib {
	_originPoint = NSMakePoint( 0.0 , 0.0 );
//	[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector( timerFired: ) userInfo:NULL repeats:YES];
}

- (void) reshape
{ 
	if( _map != NULL ) {
		NSRect sceneBounds;
		[ [ self openGLContext ] update ];
		sceneBounds = [ self frame ];
		// Reset current viewport
		glViewport( 0, 0,  [_map width] * 32 , [_map height] * 32 );
		glMatrixMode( GL_PROJECTION );   // Select the projection matrix
		glLoadIdentity();                // and reset it
		glOrtho( 0.0 , (GLsizei)[_map width] * 32 , 0.0 , (GLsizei)  [_map height] * 32 , 0, 10.0 );
		glMatrixMode( GL_MODELVIEW );    // Select the modelview matrix
		glLoadIdentity();                // and reset it

		float visibleWidth = [(NSClipView *)[self superview] documentVisibleRect].size.width;
		float visibleHeight = [(NSClipView *)[self superview] documentVisibleRect].size.height;
		
		_viewPort = NSMakeRect( 0,0, visibleWidth, visibleHeight );
		//NSLog(NSStringFromRect(_viewPort));
		glViewport( 0.0 , 0.0 , _viewPort.size.width , _viewPort.size.height );
		
		float size[2];
		glGetFloatv( GL_MAX_VIEWPORT_DIMS , size);
		NSLog(@"MAX DIMS = %f,%i", size[0], size[1] );
	}
}

- (void)timerFired:(NSTimer *)aTimer {
	[self setNeedsDisplay:YES];
}

- (void)buildGeometry {
}
- (float)scaleFactor {
	return 1.0f;
}
- (void)drawRect:(NSRect)rect {
	if( _palette == NULL ||
		_tileList == NULL ||
		_pieceList == NULL ||
		_groupList == NULL ||
		_map == NULL ) {
			return;
		}
	glClearColor( 1.0, 0.0, 0.0, 1.0 );
	glClear( GL_COLOR_BUFFER_BIT );
	
	int X = 0;
	int Y = 0;
	
	glLoadIdentity();
		
	glEnable( GL_TEXTURE_2D );
	glEnable( GL_BLEND );


	float visibleWidth = [(NSClipView *)[self superview] documentVisibleRect].size.width;
	float visibleHeight = [(NSClipView *)[self superview] documentVisibleRect].size.height;

	glScalef( [_map width] * 32 / visibleWidth , [_map height] * 32 / visibleHeight, 1.0 );

	glTranslated( _originPoint.x , _originPoint.y , 0.0 );
	GLuint curTexture = 0;
	for( X = 0; X < [_map width]; X++ ) {
		for( Y = 0 ; Y < [_map height]; Y++ ) {				
			u_int16_t mapTileID = [_map tileAtX:X Y:Y];
			int tileIndex = [_groupList indexForGroup:(mapTileID / 16) member:(mapTileID % 16)];
			int texX = [_tileList textureS:tileIndex];//tileIndex % 32 * 32;
			int texY = [_tileList textureT:tileIndex];;

			/*if( tileIndex > 0 ) {
				texY = tileIndex / 32 * 32;
				texY = texY % 1024;
			}
			
			
			int currentTexture = 0;
			if( tileIndex > 0 ) {
				currentTexture = [_tileList textureAtIndex: tileIndex / 1024 ] - 1;
			}
			*/
			
			GLuint texID = [_tileList textureID:tileIndex];
			
		//	printf("(%i,%i) => (%i,%i), %i\n", X, Y, texX, texY, texID );
		//	NSLog(@"using texture %i, text coords %ix%i, for tileindex = %i", currentTexture, texX, texY, tileIndex );
			 
		//	int textureOffset = currentTexture * 32;
			if( texID != curTexture ) {
				glBindTexture( GL_TEXTURE_RECTANGLE_ARB , texID );
				curTexture = texID;
			}
			glBegin(GL_QUADS);
				glTexCoord2i( texX, texY + 32);
				glVertex2i( X * 32, Y * 32);
				glTexCoord2i( texX + 32, texY + 32 );
				glVertex2i( (X+1) * 32, Y * 32);
				glTexCoord2i( texX + 32, texY );
				glVertex2i( (X+1) * 32, (Y+1) * 32);
				glTexCoord2i( texX, texY);
				glVertex2i( X * 32, (Y+1) * 32);
			glEnd();
		}
	}
	
	
	
	glEnable( GL_CLIP_PLANE0 );
	double equation[4] = { 1.0, 1.0, 1.0, 0.0 };
	glClipPlane( GL_CLIP_PLANE0 , equation );
	
	[miniMapView setNeedsDisplay:YES];
	glFinish();
	//[[self openGLContext] 
	//[[self openGLContext] flushBuffer];
}

/* Scrollers */
- (void)_doScroller:(id)sender {
	//NSLog( @"%@ -> %@",  NSStringFromSelector(_cmd), NSStringFromRect( [sender rectForPart:[sender hitPart]]));
	if( sender == _horizontalScroller ) {
		float possibleWidth = [ _map width ] * 32 - [(NSClipView *)[self superview] documentVisibleRect].size.width;
		_originPoint.x =  -1 * [sender floatValue] * possibleWidth;
	} else if( sender == _verticalScroller ) {
		float possibleHeight = [ _map height ] * 32 - [(NSClipView *)[self superview] documentVisibleRect].size.height;
		_originPoint.y = -1 * (possibleHeight -  [sender floatValue] * possibleHeight);
	}

	[self setNeedsDisplay:YES];
}

- (NSRect)visibleMapRect {
	float visibleWidth = [(NSClipView *)[self superview] documentVisibleRect].size.width;
	float visibleHeight = [(NSClipView *)[self superview] documentVisibleRect].size.height;
	return NSMakeRect( -_originPoint.x, -_originPoint.y, visibleWidth, visibleHeight );
}

- (void)setHorizontalScroller:(NSScroller *)scroller {
	if( scroller != _horizontalScroller ) {
		[_horizontalScroller release];
		_horizontalScroller = [scroller retain];
	}
}

- (void)setVerticalScroller:(NSScroller *)scroller {
	if( scroller != _verticalScroller ) {
		[_verticalScroller release];
		_verticalScroller = [scroller retain];
	}
}

- (void)setTileMap:(TileMap *)map
{
	if( map != _map ) {
		[_map release];
		_map = [map retain];
		[self setFrameSize:NSMakeSize( [_map width] * 32  , [_map height] * 32  )];
		[self reshape];
	}
}

- (void)setTilePieceList:(TilePieceList *)pieceList {
	if( pieceList != _pieceList ) {
		[_pieceList release];
		_pieceList = [pieceList retain];
	}
}

- (void)setTileGroupList:(TileGroupList *)groupList {
	if( groupList != _groupList ) {
		[_groupList release];
		_groupList = [groupList retain];
	}
}

- (void)setTileList:(TileList *)tileList {
	if( tileList != _tileList ) {
		[_tileList release];
		_tileList = [tileList retain];
	}
}

- (void)setPalette:(ColorPalette *)palette {
	if( palette != _palette ) {
		[_palette release];
		_palette = [palette retain];
	}
}
@end
